package com.springboot.job.schedule;

import com.springboot.job.utils.SpringContainerContext;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Objects;

/**
 *  定时任务work线程
 */
@Slf4j
public class TaskRunnable implements Runnable{

    private String beanName;

    private String methodName;

    private String params;

    public TaskRunnable(String beanName, String methodName, String params){
        this.beanName = beanName;
        this.methodName = methodName;
        this.params = params;
    }

    public TaskRunnable(String beanName, String methodName){
        this(beanName, methodName, null);
    }

    @Override
    public void run() {
        log.info("begin run task ！beanName[{}], method [{}], params [{}]", this.beanName, this.methodName, this.params);

        Object target = SpringContainerContext.getBean(this.beanName);

        Assert.notNull(target, "target task can not null");

        Class<?> targetClass = target.getClass();

        try {
            Method method;

            if(!StringUtils.isEmpty(params)){
                method = targetClass.getDeclaredMethod(this.methodName, String.class);
            }else {
                method = targetClass.getDeclaredMethod(this.methodName);
            }

            Assert.notNull(method, "task method can not null");

            method.setAccessible(true);

            // 执行方法
            if(!StringUtils.isEmpty(params)){
                method.invoke(target, this.params);
            }else {
                method.invoke(target);
            }
        } catch (NoSuchMethodException | InvocationTargetException | IllegalAccessException e) {
            log.error("beanName:{}, beanMethod:{} task run error", this.beanName, this.methodName, e);
        }

        log.info("begin run success ！beanName[{}], method [{}], params [{}]", this.beanName, this.methodName, this.params);
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        TaskRunnable that = (TaskRunnable) o;
        if (params == null) {
            return beanName.equals(that.beanName) &&
                    methodName.equals(that.methodName) &&
                    that.params == null;
        }

        return beanName.equals(that.beanName) &&
                methodName.equals(that.methodName) &&
                params.equals(that.params);
    }

    @Override
    public int hashCode() {
        if (params == null) {
            return Objects.hash(beanName, methodName);
        }

        return Objects.hash(beanName, methodName, params);
    }
}
